package org.example.controller;

import com.wf.captcha.SpecCaptcha;
import com.wf.captcha.base.Captcha;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.example.dao.CommentDao;
import org.example.dao.LabelDao;
import org.example.pojo.*;
import org.example.pojo.Label;
import org.example.response.ResponseResult;
import org.example.response.ResponseState;
import org.example.utils.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.util.Date;
import java.util.List;

@Transactional
@Slf4j
@RestController
@RequestMapping("/test")
public class TestController {

    @Autowired
    private IdWorker idWorker;
    @Autowired
    private LabelDao labelDao;
    private Claims claims;

    @GetMapping(value = "/hello-world")
    public ResponseResult helloWorld() {
        log.info("hello world");
        //读取保存到redis里的值
        String captchaContent = (String) redisUtil.get(Constants.User.KEY_CAPTCHA_CONTENT + "123456");
        log.info("captcha content: {}", captchaContent);
        return ResponseResult.SUCCESS().setData("hello world");
    }

    @GetMapping("/json")
    public ResponseResult testJson() {
        Users users = new Users("特朗普", "male", 73);
        House house = new House("白宫", "华盛顿特区-宾夕法尼亚州大道");
        users.setHouse(house);
        return ResponseResult.SUCCESS().setData(users);
    }

    @PostMapping("/login")
    public ResponseResult login(@RequestBody Users users) {
        log.info("login:{} {}", users.getUsername(), users.getPassword());
        ResponseResult responseResult = new ResponseResult(ResponseState.LOGIN_SUCCESS);
        return responseResult.setData(users);
    }

    //增
    @PostMapping("/label")
    public ResponseResult addLabel(@RequestBody Label label) {
        //判断数据是否有效
        //补全数据
        label.setId(String.valueOf(idWorker.nextId()));
        label.setCreateTime(new Date());
        label.setUpdateTime(new Date());
        //保存数据
        log.info("add label success");
        labelDao.save(label);
        return ResponseResult.SUCCESS("测试标签添加成功！");
    }

    //删
    @DeleteMapping("/label/{labelId}")
    public ResponseResult deleteLabel(@PathVariable String labelId) {
        log.info("deleteLabel:{}", labelId);
        int deleteResult = labelDao.deleteOneById(labelId);
        log.info("删除标签状态:{}", deleteResult);
        if (deleteResult > 0) {
            return ResponseResult.SUCCESS("删除标签成功！");
        } else {
            return ResponseResult.FAILURE("标签不存在！");
        }
    }

    //改
    @PutMapping("/label/{labelId}")
    public ResponseResult updateLabel(@PathVariable String labelId, @RequestBody Label label) {
        log.info("updateLabel:{}", label);
        Label dbLabel = labelDao.findOneById(labelId);
        if (dbLabel == null) {
            return ResponseResult.FAILURE("标签不存在！");
        }
        dbLabel.setCount(label.getCount());
        dbLabel.setName(label.getName());
        dbLabel.setUpdateTime(new Date());
        labelDao.save(dbLabel);
        return ResponseResult.SUCCESS("标签修改成功！");
    }

    //查
    @GetMapping("/label/{labelId}")
    public ResponseResult getLabelById(@PathVariable String labelId) {
        Label dbLabel = labelDao.findOneById(labelId);
        if (dbLabel == null) {
            return ResponseResult.FAILURE("标签不存在！");
        }
        return ResponseResult.SUCCESS("获取标签成功！").setData(dbLabel);
    }

    //获取列表（分页查询）
    @GetMapping("/label/list/{page}/{size}")
    public ResponseResult listLabel(@PathVariable int page, @PathVariable int size) {
        if (page < 1) {
            page = 1;
        }
        if (size <= 0) {
            size = Constants.DEFAULT_SIZE;
        }

        //排序
        Sort sort = Sort.by(Sort.Direction.ASC, "createTime");

        Pageable pageable = PageRequest.of(page - 1, size, sort);
        Page<Label> result = labelDao.findAll(pageable);
        return ResponseResult.SUCCESS("获取成功！").setData(result);
    }

    //模糊查询（根据名称查询）
    @GetMapping("/label/search")
    public ResponseResult doLabelSearch(@RequestParam String keyword, @RequestParam int count) {

        //全词查询
        //Label oneByName = labelDao.findOneByName(keyword);

        List<Label> all = labelDao.findAll(new Specification<Label>() {
            @Override
            public Predicate toPredicate(Root<Label> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                //全词匹配
                //Predicate namePre = cb.equal(root.get("name").as(String.class), keyword);

                //模糊查询 多条件 “%”前后占位符
                Predicate namePre = cb.like(root.get("name").as(String.class), "%" + keyword + "%");
                Predicate countPre = cb.equal(root.get("count").as(Integer.class), count);
                return cb.and(namePre, countPre);
            }
        });
        if (all.isEmpty()) {
            return ResponseResult.FAILURE("结果为空！");
        }
        return ResponseResult.SUCCESS("查找成功！").setData(all);
    }

    @Autowired
    private RedisUtil redisUtil;

    @RequestMapping("/captcha")
    public void captcha(HttpServletRequest request, HttpServletResponse response) throws Exception {
        // 设置请求头为输出图片类型
        response.setContentType("image/gif");
        response.setHeader("Pragma", "No-cache");
        response.setHeader("Cache-Control", "no-cache");
        response.setDateHeader("Expires", 0);

        // 三个参数分别为宽、高、位数
        SpecCaptcha specCaptcha = new SpecCaptcha(130, 48, 5);
        // 设置字体
        specCaptcha.setFont(new Font("Verdana", Font.PLAIN, 32));  // 有默认字体，可以不用设置
        // 设置类型，纯数字、纯字母、字母数字混合
        specCaptcha.setCharType(Captcha.TYPE_ONLY_NUMBER);

        String content = specCaptcha.text().toLowerCase();
        // 验证码存入session
        //request.getSession().setAttribute("captcha", specCaptcha.text().toLowerCase());
        //log.info("captcha:{}", specCaptcha.text());

        //保存到redis里，10分钟有效
        redisUtil.set(Constants.User.KEY_CAPTCHA_CONTENT + "123456", content, 60 * 10);

        // 输出图片流
        specCaptcha.out(response.getOutputStream());
    }

    @Autowired
    private CommentDao commentDao;

    @PostMapping("/comment")
    public ResponseResult testComment(@RequestBody Comment comment, HttpServletRequest request) {
        String content = comment.getContent();
        log.info("testComment:{}", content);
        //还得知道是谁评论，对这个评论身份进行确认

        String cookieValue = CookieUtils.getCookie(request, Constants.User.COOKIE_TOKEN_KEY);
        if (cookieValue == null) {
            return ResponseResult.FAILURE("账号未登录！");
        }
        String token = (String) redisUtil.get(Constants.User.KEY_TOKEN + cookieValue);
        if (token == null) {
            //空的话就是过期了，但是有可能登录过，可以去查refreshToken
            //TODO:
            //如果refreshToken不存在，或者已经过期
            //告诉用户账户未登录
        }

        //已经登录了，解析token
        Claims claims = null;
        try {
            claims = JwtUtil.parseJWT(token);
        } catch (Exception e) {
            //过期了，但是有可能登录过，可以去查refreshToken
            //如果refreshToken不存在，或者已经过期
            //告诉用户账户未登录
            return ResponseResult.FAILURE("账号未登录！");
        }
        if (claims == null) {
            return ResponseResult.FAILURE("账号未登录！");
        }

        SobUser sobUser = ClaimsUtils.claims2SobUser(claims);
        comment.setUserId(sobUser.getId());
        comment.setUserName(sobUser.getUserName());
        comment.setUserAvatar(sobUser.getAvatar());
        comment.setCreateTime(new Date());
        comment.setUpdateTime(new Date());
        comment.setId(idWorker.nextId() + "");

        commentDao.save(comment);
        return ResponseResult.SUCCESS("评论成功！");
    }
}
